<template>
    <div v-if="currentComponent" class="condition-form">
        <span v-if="currentComponent.label" class="nlabel">{{ currentComponent.label }}</span>
        <component
            :is="currentComponent.componentValue"
            ref="conditionForm"
            v-model:value="editConditionData.value"
            class="input-width"
            :column-info="columnInfo"
            v-bind="currentComponent.props"
        />
        <span class="error-label">{{ errorMsg }}</span>
    </div>
</template>

<script lang="ts">
    import { defineComponent, ref, watch, computed } from 'vue'
    import { useI18n } from 'vue-i18n'
    import { getComponent } from './conditionFormConfig'
    import { isArray } from '@/utils/is'

    export default defineComponent({
        props: {
            columnInfo: {
                type: Object,
                require: true,
                default: () => ({ type: 'VARCHAR' })
            },
            conditionData: {
                type: Object,
                default: () => ({
                    conditionType: '',
                    value: ''
                })
            }
        },
        setup(props) {
            const { t } = useI18n()

            const conditionForm = ref()

            const errorMsg = ref<string>('')
            const editConditionData = ref()

            watch(
                () => props.conditionData,
                () => {
                    editConditionData.value = props.conditionData
                },
                {
                    immediate: true,
                    deep: true
                }
            )

            // 调用组件内部的校验方法
            function customValidate() {
                const component = conditionForm.value
                if (component && component.validate) {
                    return component.validate()
                }
                return Promise.resolve()
            }

            // 组件必填校验
            function requiredValidate() {
                const { value } = editConditionData.value
                if ((value !== 0 && !value) || (isArray(value) && !value.length)) {
                    return Promise.reject(t('placeholderInput'))
                }
                return Promise.resolve()
            }

            // 校验表达式的值
            function validate() {
                errorMsg.value = '' // 清空校验错误信息
                const validatorMap = {
                    require: requiredValidate,
                    custom: customValidate
                }
                const { validate } = currentComponent.value || {}
                if (validate && validatorMap[validate]) {
                    return validatorMap[validate]().catch(error => {
                        errorMsg.value = error
                        return Promise.reject()
                    })
                }

                return Promise.resolve()
            }

            watch(
                () => editConditionData.value.value,
                () => {
                    // 条件表达式的值发生变化，对结果进行校验
                    validate()
                },
                {
                    deep: true
                }
            )

            const currentComponent = computed(() => {
                const { type } = props.columnInfo
                const { conditionType } = props.conditionData || {}
                return getComponent(type, conditionType)
            })
            return {
                editConditionData,
                currentComponent,
                errorMsg,

                conditionForm
            }
        }
    })
</script>

<style lang="less" scoped>
    .condition-form {
        display: flex;
        align-items: center;

        .nlabel {
            margin-right: 10px;
        }

        .error-label {
            color: red;
            margin-left: 10px;
        }

        .input-width {
            width: 300px;
        }
    }
</style>
